#!/usr/bin/env perl
# Simple file to UDP and TCP checking with iperf

# ./chkUDP.pl [same options as wrekaUDP.pl]
# Basile Clout, October 2007

use Getopt::Long;

use strict;

my $wrekaUDP_bin = "../daemons/wrekaUDP.pl";
my $wmapd_bin = "../daemons/hemapd.py";

my $iperf_time = 5;
my $iperf_proto = "udp";
my $iperf_server_list = "lids02 lids04 lids05 lids06 lids09 lids13 lids15 lids16";
my $iperf_server_file = "";
my $log_file = "chkUDP.log";
my $iperf_bin_server = "/root/config/code/iperf-1.7.0/iperf";
my $iperf_bin_client = "iperf";
my $ssh_bin = "yes ' ' | rsh";
my $ssh_bin_ms = "ssh"; 
my $help;
my $user = "root";
my $fast;

GetOptions("t=i"=>\$iperf_time, "p=s"=>\$iperf_proto,"c=s"=>\$iperf_server_list, "f=s"=>\$iperf_server_file, "log=s"=>\$log_file, "iperf_server=s"=>\$iperf_bin_server, "iperf_client=s"=>\$iperf_bin_client, "r=s"=>\$ssh_bin, "rms=s"=>\$ssh_bin_ms, "u=s"=>\$user, "h"=>\$help, "fast"=>\$fast);

if ($help){

	print "Usage: ./chkUDP.pl [-c list of nodes] [-f file
	containing nodes] [-t time] [-p protocol (\"udp\" or \"tcp\")]
	[--log log file] [--iperf_server path of iperf on the servers]
	[--iperf_client path of iperf on the client] [-r network
	protocol (ssh, rsh, ...)] [-u user] [-h this help] [--fast
	check only once per link (instead of 2)] \nExample:
	./wrekaUDP.pl -p udp -t 3 --log mylog.log -f lamhosts.txt -r
	ssh -u basil\n\n";

exit(1); 
}

die "ERROR: No node given. Please specify a list of nodes belonging to the cluster (with the -c or -f switch)!" if ($iperf_server_list eq "" && $iperf_server_file eq "");


# Check remote connecter
if ($ssh_bin !~ /rsh/ && $ssh_bin !~ /ssh/) {
  warn "WARNING: the network protocol $ssh_bin is strange ...";
  print LOG "WARNING: the network protocol $ssh_bin is strange ...\n";
}

# Open log descriptor
open LOG, ">$log_file" or die "Impossible to open ".$log_file.": $!";
my ($sec, $min, $hrs, $day, $month, $year) = (localtime) [0,1,2,3,4,5];
my $date = sprintf("%04d-%02d-%02d %d:%d:%d\n", $year+1900, $month+1, $day, $hrs, $min, $sec);
print LOG "chkUDP log, Basile Clout, ".$date;

my @iperf_servers;

# Put servers in an array
if ($iperf_server_file ne ""){
  open FILE, "<$iperf_server_file" or die "Impossible to open servers file ".$iperf_server_file.": $!";
  my @iperf_servers_line = <FILE>;
  @iperf_servers=split /\s+/, $iperf_servers_line[$#iperf_servers_line];
}else{
  @iperf_servers=split /\s+/, $iperf_server_list;
}
print LOG "Connect to:".join(' ', @iperf_servers)."\n";

#print "# 1st line: time (in s) for each iperf measurement, number of node in the cluster, protocol\n";
#print "# 2nd line: the nodes in the cluster being mapped\n";
#print "# Other lines: \n";
#print "# \t base_node bandwidths (MBits/s)\n";
#print "# \t\t latencies (ms)\n";
print "$iperf_time ".scalar($#iperf_servers+1)." $iperf_proto\n";
printf "\t";

@iperf_servers = sort @iperf_servers;
foreach (@iperf_servers) {
  printf "%s\t", $_;
}
print "\n";

my %wrekaUDP_hash;
my $cnt = 0;

foreach my $server (@iperf_servers) {
  
  print LOG "@ $server:\n";
  my @tmp_list = @iperf_servers;
  
  if ($fast){
    for(my $i=0; $i<$cnt;$i++){
      my $shifted = shift @tmp_list;
      $wrekaUDP_hash{$shifted} = ['  -','  -'];
    }
  }

  my $wrekaUDP_args = "-c \\\"".join(' ', @tmp_list)."\\\" -t $iperf_time -p $iperf_proto --log \\\"$log_file.part\\\" --iperf_client \\\"$iperf_bin_client\\\" --iperf_server \\\"$iperf_bin_server\\\" -r \\\"$ssh_bin\\\" -u \\\"$user\\\" ";
  my $order = "$ssh_bin_ms ${user}\@${server} \"$wrekaUDP_bin $wrekaUDP_args\"";
  print LOG "Order: $order\n";

  my $pid = open(WREKAUDP, "$order |");
  waitpid $pid,0;
  my @out_wrekaUDP = <WREKAUDP>;
  print LOG "Local wrekaUDP: ".join(' ',@out_wrekaUDP)."\n";


  foreach my $line (@out_wrekaUDP) {    
    chomp $line;
    my @parts = split / /,$line; 
    if($#parts == 2){
      $wrekaUDP_hash{$parts[0]} = [ $parts[1], $parts[2] ];
    }
  }
  $wrekaUDP_hash{$server} = [ "  -", "  -" ];
  
  print "$server\t";		# Print bandwidth
  foreach (@iperf_servers) {
    print " $wrekaUDP_hash{$_}[0]\t";
  }
  print "\n\t";
  foreach (@iperf_servers) {	# Print latency
    print " $wrekaUDP_hash{$_}[1]\t";
  }
  print "\n";
  $cnt++;
  
  close(WREKAUDP);
}


